package com.vue3.blog.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.net.NetUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vue3.blog.common.resp.BizException;
import com.vue3.blog.common.resp.PageVO;
import com.vue3.blog.common.util.PageUtil2;
import com.vue3.blog.common.util.StpUtil2;
import com.vue3.blog.common.util.StrUtil2;
import com.vue3.blog.domain.dto.ArticleDTO;
import com.vue3.blog.domain.dto.ArticleQueryDTO;
import com.vue3.blog.domain.entity.ArticleEntity;
import com.vue3.blog.domain.vo.ArticleDetailVO;
import com.vue3.blog.mapper.ArticleMapper;
import com.vue3.blog.service.IArticleService;
import com.vue3.blog.service.ICategoryService;
import com.vue3.blog.service.ISysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Mr.小朱同学
 * @version 1.0.0
 * @date 2025/6/9 19:10
 * @description 博客文章
 */
@Service
public class ArticleService extends ServiceImpl<ArticleMapper, ArticleEntity> implements IArticleService {
    @Value("${server.port}")
    private int port;
    @Resource
    private ICategoryService categoryService;
    @Resource
    private ISysUserService sysUserService;

    /**
     * 保存文章
     */
    @Override
    public void saveArticle(ArticleDTO dto) {
        ArticleEntity entity = new ArticleEntity();
        if (dto.getId() != null) {
            entity = this.getById(dto.getId());
        } else {
            entity.setCreatedTime(new Date());
            entity.setLikes(0);
        }
        entity.setTitle(dto.getTitle());
        entity.setBrief(dto.getBrief());
        entity.setCoverImage(StrUtil2.delProtocol(dto.getCoverImage()));
        entity.setContent(dto.getContent());
        entity.setCategoryId(dto.getCategoryId());
        entity.setUpdatedTime(new Date());
        entity.setStatus(dto.getStatus());
        if (Objects.equals(0, dto.getStatus())) {
            entity.setStatus(0);
        } else if (Objects.equals(1, dto.getStatus())) {
            entity.setStatus(1);
            entity.setPublishedTime(new Date());
        }
        entity.setUserId(StpUtil2.getLoginId());
        // todo 记录文章和标签之间的关系
        this.saveOrUpdate(entity);
    }

    /**
     * 删除文章
     *
     * @param id 文章ID
     */
    @Override
    public void removeArticle(Long id) {
        ArticleEntity entity = this.getById(id);
        if (null == entity) {
            throw new BizException("文章不存在");
        }
        entity.setStatus(2);
        entity.setUpdatedTime(new Date());
        this.updateById(entity);
    }

    /**
     * 获取文章详情
     *
     * @param id 文章ID
     */
    @Override
    public ArticleDetailVO getArticleDetail(Long id) {
        ArticleQueryDTO dto = new ArticleQueryDTO();
        dto.setId(id);
        dto.setIsGetContent(1);
        dto.setIsPage(0);
        PageVO<ArticleDetailVO> voList = getArticleList(dto);
        if (CollUtil.isEmpty(voList.getRecord())) {
            return new ArticleDetailVO();
        }
        return voList.getRecord().get(0);
    }

    /**
     * 获取上一篇、下一篇文章
     *
     * @param id 文章ID
     */
    @Override
    public Map<String, ArticleDetailVO> getPrevNextArticle(Long id) {
        Map<String, ArticleDetailVO> ansMap = new HashMap<>();
        // 查询比 id 小的第一篇文章
        LambdaQueryWrapper<ArticleEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.lt(ArticleEntity::getId, id);
        wrapper.orderByDesc(ArticleEntity::getId);
        wrapper.last("LIMIT 1");
        ArticleEntity article = this.getOne(wrapper);
        if (null != article) {
            ArticleDetailVO vo = new ArticleDetailVO();
            vo.setId(article.getId());
            vo.setTitle(article.getTitle());
            ansMap.put("prev", vo);
        }

        // 查询比 id 大的第一篇文章
        wrapper = Wrappers.lambdaQuery();
        wrapper.gt(ArticleEntity::getId, id);
        wrapper.orderByAsc(ArticleEntity::getId);
        wrapper.last("LIMIT 1");
        article = this.getOne(wrapper);
        if (null != article) {
            ArticleDetailVO vo = new ArticleDetailVO();
            vo.setId(article.getId());
            vo.setTitle(article.getTitle());
            ansMap.put("next", vo);
        }
        return ansMap;
    }

    /**
     * 文章列表
     */
    @Override
    public PageVO<ArticleDetailVO> getArticleList(ArticleQueryDTO dto) {
        LambdaQueryWrapper<ArticleEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(dto.getId() != null, ArticleEntity::getId, dto.getId());
        wrapper.like(StrUtil2.isNotEmpty(dto.getTitle()), ArticleEntity::getTitle, dto.getTitle());
        wrapper.eq(dto.getCategoryId() != null, ArticleEntity::getCategoryId, dto.getCategoryId());
        wrapper.in(CollUtil.isNotEmpty(dto.getStatusList()), ArticleEntity::getStatus, dto.getStatusList());
        wrapper.orderByDesc(ArticleEntity::getCreatedTime);
        if (Objects.equals(1, dto.getIsPage())) {
            PageUtil2.startPage();
        }
        List<ArticleEntity> entityList = this.list(wrapper);
        if (CollectionUtils.isEmpty(entityList)) {
            return PageUtil2.endPage(Collections.emptyList());
        }
        Map<Long, String> categoryIdAndNameMap = categoryService.getCategoryIdAndNameMap();
        // 查询当前
        Set<Long> userIdSet = entityList.stream().map(ArticleEntity::getUserId).collect(Collectors.toSet());
        Map<Long, String> sysUserNameMap = sysUserService.getSysUserNameMap(userIdSet);

        String localIp = NetUtil.getLocalhostStr();
        List<ArticleDetailVO> voList = new ArrayList<>();
        entityList.forEach(ent -> {
            ArticleDetailVO vo = new ArticleDetailVO();
            BeanUtils.copyProperties(ent, vo);
            if (Objects.equals(0, dto.getIsGetContent())) {
                vo.setContent("");
            }
            if (StrUtil2.isNotEmpty(vo.getCoverImage())) {
                vo.setCoverImage("http://" + localIp + ":" + port + vo.getCoverImage());
            }
            vo.setCategoryName(categoryIdAndNameMap.getOrDefault(ent.getCategoryId(), ""));
            vo.setAuthorName(sysUserNameMap.getOrDefault(ent.getUserId(), ""));
            voList.add(vo);
        });
        return PageUtil2.endPage(entityList, voList);
    }

    /**
     * 获取最新发布的6篇文章
     */
    @Override
    public List<ArticleDetailVO> getNewArticleList() {
        LambdaQueryWrapper<ArticleEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.select(ArticleEntity::getId, ArticleEntity::getTitle);
        wrapper.eq(ArticleEntity::getStatus, 1);
        wrapper.orderByDesc(ArticleEntity::getPublishedTime);
        wrapper.last("limit 6");
        List<ArticleEntity> entityList = this.list(wrapper);
        if (CollUtil.isEmpty(entityList)) {
            return Collections.emptyList();
        }
        List<ArticleDetailVO> voList = new ArrayList<>();
        entityList.forEach(ent -> {
            ArticleDetailVO vo = new ArticleDetailVO();
            BeanUtils.copyProperties(ent, vo);
            voList.add(vo);
        });
        return voList;
    }

    /**
     * 统计文章数量
     */
    @Override
    public Long getArticleCount(Integer... status) {
        LambdaQueryWrapper<ArticleEntity> wrapper = Wrappers.lambdaQuery();
        if (status != null && status.length > 0) {
            wrapper.in(ArticleEntity::getStatus, Arrays.asList(status));
        }
        return this.count(wrapper);
    }
}